package com.webank.maling.app;

import com.webank.maling.ai.vector.VectorGenerator;
import com.webank.maling.analyzer.java.context.GraphContext;
import com.webank.maling.analyzer.java.processor.*;
import com.webank.maling.analyzer.java.rule.SpoonEntryPointRuleEngine;
import com.webank.maling.base.config.AppConfig;
import com.webank.maling.base.enums.RuleEngineType;
import com.webank.maling.base.util.FileTool;
import com.webank.maling.repository.milvus.GraphVectorMilvusClient;
import com.webank.maling.repository.nebula.NebulaGraphClient;
import com.webank.maling.rule.factory.RuleEngineFactory;
import lombok.extern.slf4j.Slf4j;
import spoon.Launcher;
import spoon.compiler.Environment;
import spoon.processing.ProcessingManager;
import spoon.reflect.factory.Factory;
import spoon.support.QueueProcessingManager;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;

@Slf4j
public abstract class AbstractHandler {
    private static boolean ruleEngineInitialized = false;

    public AbstractHandler(){
        initializeRuleEngine();
    }

    /**
     * 初始化规则引擎（只初始化一次）
     */
    private synchronized void initializeRuleEngine() {
        if (!ruleEngineInitialized) {
            RuleEngineFactory factory = RuleEngineFactory.getInstance();
            if (!factory.hasEngine(RuleEngineType.JAVA_ENTRY_POINT)) {
                SpoonEntryPointRuleEngine entryPointEngine = new SpoonEntryPointRuleEngine();
                factory.registerEngine(entryPointEngine);
                log.info("Registered java entry point rule engine");
            }
            ruleEngineInitialized = true;
        }
    }

    public void handle() {
        log.info("Starting Java Graph Builder");

        // 初始化客户端
        try (NebulaGraphClient nebulaClient = new NebulaGraphClient();
             GraphVectorMilvusClient graphVectorMilvusClient = new GraphVectorMilvusClient()) {

            // 初始化向量生成器
            VectorGenerator vectorGenerator = new VectorGenerator();

            GraphContext.GraphContextBuilder graphContextBuilder = GraphContext.builder()
                    .nebulaGraphClient(nebulaClient)
                    .graphVectorMilvusClient(graphVectorMilvusClient)
                    .vectorGenerator(vectorGenerator);

            GraphContext graphContext = initGraphContext(graphContextBuilder);

            // 初始化Spoon
            Launcher launcher = new Launcher();
            initLauncher(launcher);

            // 配置Spoon环境
            Environment environment = launcher.getEnvironment();
            environment.setAutoImports(true);
            environment.setCommentEnabled(true);
            environment.setComplianceLevel(8); // Java 17
            environment.setIgnoreDuplicateDeclarations(true);
            environment.setIgnoreSyntaxErrors(true);
            AppConfig appConfig = AppConfig.getInstance();
            // 获取全局库路径
            String globalLibraryPath = appConfig.getGlobalLibraryPath();
            URL[] jarPaths = FileTool.getAllJarUrls(globalLibraryPath);
            environment.setInputClassLoader(new URLClassLoader(jarPaths, null));
            log.info("Added {} jar files to source classpath", jarPaths.length);

            // 构建模型
            launcher.buildModel();
            Factory factory = launcher.getFactory();
            ProcessingManager processingManager = new QueueProcessingManager(factory);

            // 添加处理器
            processingManager.addProcessor(new FileProcessor(graphContext));
            processingManager.addProcessor(new ClassProcessor(graphContext));

            //创建依赖注入处理器
            DependencyInjectionProcessor dependencyInjectionProcessor = new DependencyInjectionProcessor(graphContext);
            processingManager.addProcessor(dependencyInjectionProcessor);

            //先执行依赖注入处理
            log.info("Processing dependency injection...");
            processingManager.process(factory.getModel().getAllTypes());

            //获取依赖映射
            Map<String, String>[] dependencyMaps = dependencyInjectionProcessor.getDependencyMaps();
            Map<String, String> annotationValueToClass = dependencyMaps[1];

            //创建新的处理管理器
            processingManager = new QueueProcessingManager(factory);
            //添加其他处理器，并传入依赖映射
            processingManager.addProcessor(new MethodProcessor(graphContext, annotationValueToClass));
            processingManager.addProcessor(new ConstructorProcessor(graphContext, annotationValueToClass));
            processingManager.addProcessor(new AnnotationProcessor(graphContext));

            // 添加RPC处理器
            processingManager.addProcessor(new RpcProcessor(graphContext));

            // 执行处理
            log.info("Processing Java code...");
            processingManager.process(factory.CompilationUnit().getMap().values());
            processingManager.process(factory.getModel().getAllTypes());
            log.info("Java Graph Builder completed successfully");
        } catch (Exception e) {
            log.error("Failed to build Java Graph", e);
        }
    }

    abstract GraphContext initGraphContext(GraphContext.GraphContextBuilder graphContextBuilder);

    abstract void initLauncher(Launcher launcher);
}
